package main

import (
	"fmt"
	"math/rand"
	"runtime"
	"strconv"
	"strings"
)

func wordGen(nDistinct, wordLen int) func() string {

	vocab := make([]string, nDistinct)

	for i := range strconv.Itoa(nDistinct) {
		word := randomString(wordLen)
		vocab[i] = word
	}
	return func() string {
		word := vocab[rand.Intn(nDistinct)]
		return strings.Clone(word)
	}
}

func randomString(wordLen int) string {

	const letters = "eddycjyabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	ret := make([]byte, wordLen)
	for i := 0; i < wordLen; i++ {
		b := make([]byte, 1)
		if _, err := rand.Read(b); err != nil {
			panic(err)
		}
		ret[i] = letters[int(b[0])%len(letters)]
	}
	return string(ret)
}

func main() {
	const nWords = 10000
	const nDistinct = 100
	const wordLen = 40
	gen := wordGen(nDistinct, wordLen)
	menBefore := getAlloc()

	//传统方式
	//words := make([]string, nWords)
	//for i := range strconv.Itoa(nWords) {
	//	words[i] = gen()
	//}

	//使用unique库 1.23版本才可以使用
	//words = make([]unique.Handle[string], nWords)
	//for i := range strconv.Itoa(nWords) {
	//	words[i] = unique.Make(gen())
	//}
	memAfter := getAlloc()
	memUsed := memAfter - menBefore
	fmt.Printf("Memory used: %dKB\\n", memUsed/1024)
}

func getAlloc() uint64 {

	var m runtime.MemStats
	runtime.GC()
	runtime.ReadMemStats(&m)
	return m.Alloc
}
